/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.inmp.util;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.inmp.cache.CacheFactory;
import com.sinodata.bsm.inmp.cache.ResCache;
import com.sinodata.bsm.inmp.conf.CPU;
import com.sinodata.bsm.inmp.conf.ConfManager;
import com.sinodata.bsm.inmp.conf.MEM;
import com.sinodata.bsm.inmp.conf.NetDevice;
import com.sinodata.bsm.inmp.conf.NetType;
import com.sinodata.bsm.inmp.conf.PORT;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangyazhou
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * --------------------------------------------------r1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class WebServiceUtil {

    private static final Logger logger = Logger.getLogger(WebServiceUtil.class);

    private static WebServiceUtil instance = null;

    private Map<String, String> jobTypeMap = new HashMap<String, String>();

    Service service = new Service();

    String soapaction = "http://service.hy.laneasy.com/";

    private Map<String, NetDevice> netMap = new HashMap<String, NetDevice>();

    private ResCache resCache = (ResCache) CacheFactory.getCache(ResCache.class);

    private Map<String, String> jobMap = new HashMap<String, String>();

    private static int out_time = 1000 * 60 * 2;

    String url = "";

    /**
     * 初始化webservice的url
     */
    private WebServiceUtil() {
        url = (String) SystemContext.getProperty("wsurl") + "/com/itsm/openapi/nwdService?wsdl";
        logger.info("[TIP]\t Init--" + url);

    }

    public static synchronized WebServiceUtil getInstance() {
        if (instance == null) {
            instance = new WebServiceUtil();
        }
        return instance;
    }

    /**
     * 获取所有的网络节点
     */
    @SuppressWarnings("unchecked")
    public List<String[]> getNetNodeList() {
        List<String[]> list = new ArrayList<String[]>();
        try {
            Call call = initCall();
            call.setOperationName(new QName(soapaction, "getNetworkDeviceList"));
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + "getNetworkDeviceList");
            String v = (String) call.invoke(new Object[] {});//调用方法并传递参数

            //            System.out.println(v);

            SAXReader reader = new SAXReader();

            Document doc = reader.read(new ByteArrayInputStream(v.getBytes("UTF-8")));

            if (doc == null) {
                return null;
            }
            List<Element> elements = doc.selectNodes("/JOB_LIST/JOB");
            for (Element e : elements) {
                String[] stry = new String[5];
                String jobid = e.attributeValue("JOB_ID").trim();
                String nodeid = e.attributeValue("NODE_ID").trim();
                stry[0] = jobid + "," + nodeid; //内部id
                stry[1] = e.attributeValue("NAME").trim(); //名称 
                stry[2] = ""; //描述
                stry[3] = e.attributeValue("IP").trim(); //ip

                NetType nt = ConfManager.getInstance().getNetNameMap().get(e.attributeValue("NODE_TYPE").trim());

                stry[4] = nt.getType();

                //                System.out.println(stry[0] + " " + stry[1] + " " + stry[2] + " " + stry[3] + " " + stry[4]);

                jobMap.put(nodeid, jobid);
                jobTypeMap.put(stry[0], stry[4]);
                list.add(stry);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 当对一个网络资源点击资源发现时触发
     * 1 缓存一个节点的全部信息
     * 资源的属性 及子资源 都从缓存中获取
     * @return
     */
    @SuppressWarnings("unchecked")
    public void getNodeInfo(String jobId) {
        try {
            Call call = initCall();
            call.setOperationName(new QName(soapaction, "getNetworkNodeInfo"));
            call.addParameter(new QName("", "jobId"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + "getNetworkNodeInfo");
            String v = (String) call.invoke(new Object[] { jobId });//调用方法并传递参数
            SAXReader reader = new SAXReader();

            Document doc = reader.read(new ByteArrayInputStream(v.getBytes("UTF-8")));

            if (doc == null) {
                return;
            }

            NetDevice nd = new NetDevice();

            List<Element> elements = doc.selectNodes("/NWD_LIST/NODE");
            for (Element e : elements) {
                //基本属性
                nd.setNodeId(e.attributeValue("NODE_ID").trim());
                nd.setJobId(e.attributeValue("JOB_ID").trim());
                nd.setSnmpSysName(e.attributeValue("SNMP_SYS_NAME").trim());
                nd.setSnmpSysOid(e.attributeValue("SNMP_SYS_OID").trim());
                nd.setVendorId(e.attributeValue("VENDOR_ID").trim());
                nd.setDeviceType(e.attributeValue("DEVICE_TYPE").trim());
                nd.setSysService(e.attributeValue("SYS_SERVICE").trim());
                nd.setSnmpContact(e.attributeValue("SNMP_CONTACT").trim());
                nd.setSnmpContact(e.attributeValue("SNMP_CONTACT").trim());
                nd.setSnmpDesc(e.attributeValue("SNMP_DESC").trim());// SNMP_DESC

                List<MEM> mList = new ArrayList<MEM>();
                List<CPU> cList = new ArrayList<CPU>();
                List<PORT> pList = new ArrayList<PORT>();

                //cpu
                Element cpu = (Element) e.selectSingleNode("CPUS");
                List<Element> cpus = cpu.selectNodes("CPU");
                for (Element ce : cpus) {
                    CPU c = new CPU();
                    c.setJobId(jobId);
                    c.setNodeId(ce.attributeValue("ID").trim());
                    c.setInstance(ce.attributeValue("INSTANCE").trim());
                    cList.add(c);
                }
                nd.setCpuList(cList);

                //内存
                Element mem = (Element) e.selectSingleNode("MEMS");
                List<Element> mems = mem.selectNodes("MEM");
                for (Element me : mems) {
                    MEM m = new MEM();
                    m.setJobId(jobId);
                    m.setNodeId(me.attributeValue("ID").trim());
                    m.setInstance(me.attributeValue("INSTANCE").trim());
                    mList.add(m);
                }

                nd.setMemList(mList);

                //端口
                Element port = (Element) e.selectSingleNode("INTERFACES");
                List<Element> ports = port.selectNodes("INTERFACE");
                for (Element pe : ports) {
                    PORT p = new PORT();
                    p.setJobId(jobId);
                    p.setNodeId(pe.attributeValue("ID").trim());
                    p.setSnmpIndex(pe.attributeValue("SNMP_INDEX").trim());
                    p.setSnmpDesc(pe.attributeValue("SNMP_DESC").trim());
                    p.setMtu(pe.attributeValue("MTU"));
                    String speed = Math.round(Double.parseDouble(pe.attributeValue("SNMP_SPEED").trim()) / 1000D) + "Mbps";
                    p.setSnmpSpeed(speed);
                    p.setMac(pe.attributeValue("MAC").trim());
                    p.setIp(pe.attributeValue("IP").trim());
                    pList.add(p);
                }
                nd.setPortList(pList);
                netMap.put(jobId, nd);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取实时的性能指标
     */
    @SuppressWarnings("unchecked")
    public List<String[]> getRealTimePerf(String jobId) {
        List<String[]> list = new ArrayList<String[]>();
        try {
            Call call = initCall();
            call.setOperationName(new QName(soapaction, "getNetworkNodePerf"));
            call.addParameter(new QName("", "jobId"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + "getNetworkNodePerf");
            String v = (String) call.invoke(new Object[] { jobId });//调用方法并传递参数

            //            System.out.println(v);
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new ByteArrayInputStream(v.getBytes("UTF-8")));
            List<Element> elements = doc.selectNodes("/NWD_LIST/NODE");
            logger.info("[TIP]\t获取实时性能数据jobId=" + jobId);
            for (Element e : elements) {
                //取本网络设备的性能
                Element usage = (Element) e.selectSingleNode("USAGE");
                String[] ustry = new String[2];
                ustry[0] = jobId + "," + jobId;
                ustry[1] = usage.attributeValue("response").trim() + "," + usage.attributeValue("online").trim();
                list.add(ustry);
                logger.info("[TIP\t]此网络设备的性能为:响应时间=" + usage.attributeValue("response").trim() + "是否可用=" + usage.attributeValue("online").trim());

                //取CPU的实时性能
                Element cpu = (Element) e.selectSingleNode("CPU");
                List<Element> cpus = cpu.selectNodes("ITEM");
                for (Element se : cpus) {
                    String[] stry = new String[2];
                    stry[0] = jobId + "," + se.attributeValue("ID").trim() + ",1";
                    stry[1] = se.attributeValue("VALUE").trim();
                    list.add(stry);
                }

                //取内存的实时性能
                Element mem = (Element) e.selectSingleNode("MEMS");
                List<Element> mems = mem.selectNodes("MEM");
                for (Element se : mems) {
                    String[] stry = new String[2];
                    stry[0] = jobId + "," + se.attributeValue("ID") + ",16";
                    stry[1] = se.attributeValue("VALUE").trim();
                    list.add(stry);
                }

                //取接口的实时性能
                //ifInOctets,ifOutOctets,ifInErrors,ifInDiscards, ifAdminStatus,ifOperStatus from PDB_NWD_if_VARJOBID
                Element itface = (Element) e.selectSingleNode("INTERFACES");
                List<Element> itfaces = itface.selectNodes("INTERFACE");
                for (Element se : itfaces) {
                    String[] stry = new String[2];
                    stry[0] = jobId + "," + se.attributeValue("ID").trim() + ",p";
                    String admin_status = se.attributeValue("ADMIN_STATUS").trim();
                    admin_status = "1".equals(admin_status) ? "开启" : "2".equals(admin_status) ? "关闭" : "未知";
                    String oper_status = se.attributeValue("OPER_STATUS").trim();
                    oper_status = "1".equals(oper_status) ? "开启" : "2".equals(oper_status) ? "关闭" : "未知";
                    stry[1] = se.attributeValue("INOCTETS").trim() + "," + se.attributeValue("OUTOCTETS").trim() + "," + se.attributeValue("ERRORS").trim() + "," + se.attributeValue("DISCARD").trim() + "," + admin_status + "," + oper_status + "," + se.attributeValue("in_rate").trim() + "," + se.attributeValue("out_rate").trim() + "," + se.attributeValue("if_usage").trim();
                    list.add(stry);
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return list;
    }

    /**
     * 修改一个网络设备的采集周期
     * @param jobId
     * @param time
     */
    public void setCollectCycle(String jobId, String time) {
        try {
            Call call = initCall();
            call.setOperationName(new QName(soapaction, "setNwdIntervalTime"));
            call.addParameter(new QName("", "jobId"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            call.addParameter(new QName("", "patam"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + "setNwdIntervalTime");
            String retVal = (String) call.invoke(new Object[] { jobId, time });//调用方法并传递参数

            System.out.println(retVal);

        } catch (Exception e) {
            logger.error(e);
        }
    }

    /**
     * 获取一个网络设备的关系数据
     * @param jobId
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String[]> getRelationList(String topoId) {
        List<String[]> list = new ArrayList<String[]>();
        try {
            Call call = initCall();
            call.setOperationName(new QName(soapaction, "getTopoLinkInfo"));
            call.addParameter(new QName("", "topoId"), org.apache.axis.encoding.XMLType.XSD_INT, javax.xml.rpc.ParameterMode.IN);
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + "getTopoLinkInfo");
            String v = (String) call.invoke(new Object[] { "1" });//调用方法并传递参数
            SAXReader reader = new SAXReader();

            Document doc = reader.read(new ByteArrayInputStream(v.getBytes("UTF-8")));

            if (doc == null) {
                return null;
            }
            List<Element> elements = doc.selectNodes("/TOPO_LIST/TOPO/LINES/LINE");
            for (Element e : elements) {
                String[] relay = new String[3];
                String sjobid = getJobMap().get(e.attributeValue("UP_NODE_ID").trim());
                String sIntelId = sjobid + "," + e.attributeValue("UP_LINK_IF_ID") + ",p";
                Res sr = resCache.getResIdByIId(sIntelId);
                if (sr == null) {
                    continue;
                }
                relay[0] = sr.getId() + "";
                relay[1] = "203";
                String ejobid = getJobMap().get(e.attributeValue("DOWN_NODE_ID").trim());
                String eIntelId = ejobid + "," + e.attributeValue("DOWN_LINK_IF_ID") + ",p";
                Res er = resCache.getResIdByIId(eIntelId);
                if (er == null) {
                    continue;
                }
                relay[2] = er.getId() + "";
                list.add(relay);
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return list;
    }

    /**
     * 初始化call
     * @return
     */
    private Call initCall() {
        Call call = null;
        try {
            call = (Call) service.createCall();
            call.setTargetEndpointAddress(new java.net.URL(url));
            call.setTimeout(out_time);
        } catch (Exception e) {
            logger.error(e);
        }
        return call;
    }

    /**
     * 示例3 取资源的实时指标数据
     * @return
     */
    @SuppressWarnings("unused")
    private Document demo3() {
        SAXReader reader = new SAXReader();
        Document doc = null;
        try {
            doc = reader.read("inmp-conf/demo3.xml");
        } catch (Exception e) {
            logger.error(e);
        }
        return doc;
    }

    /**
     * 示例2  取资源信息
     * @return
     */
    @SuppressWarnings("unused")
    private Document demo2() {
        SAXReader reader = new SAXReader();
        Document doc = null;
        try {
            doc = reader.read("inmp-conf/demo2.xml");
        } catch (Exception e) {
            logger.error(e);
        }
        return doc;
    }

    /**
     * 示例1  取资源列表
     * @return
     */
    @SuppressWarnings("unused")
    private Document demo1() {
        SAXReader reader = new SAXReader();
        Document doc = null;
        try {
            doc = reader.read("inmp-conf/demo1.xml");
        } catch (Exception e) {
            logger.error(e);
        }
        return doc;
    }

    public Map<String, NetDevice> getNetMap() {
        return netMap;
    }

    public Map<String, String> getJobMap() {
        return jobMap;
    }

    /**
     * 测试
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        //                Service service = new Service();
        //                String url = "http://10.0.2.200:8080/com/itsm/openapi/nwdService?wsdl";
        //                String soapaction = "http://service.hy.laneasy.com/";
        //                //        String url = "http://www.webxml.com.cn/WebServices/ValidateEmailWebService.asmx?wsdl";
        //                //        String soapaction = "http://WebXml.com.cn/";
        //        
        //                Call call = null;
        //        
        //                call = (Call) service.createCall();
        //                call.setTargetEndpointAddress(new java.net.URL(url));
        //                //        call.setTargetEndpointAddress(url);
        //                call.setOperationName(new QName(soapaction, "getNetworkDeviceList"));
        //                //        call.addParameter(new QName("", "topoId"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
        //                call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
        //                call.setUseSOAPAction(true);
        //                call.setSOAPActionURI(soapaction + "getNetworkDeviceList");
        //                String v = (String) call.invoke(new Object[] {});//调用方法并传递参数
        //                //        String v = (String) call.invoke(new Object[] {});//调用方法并传递参数
        //                System.out.println(v);

        //        --------------------------------------------------------------------------------

        Service service = new Service();
        String url = "http://10.0.2.200:8080/com/itsm/openapi/nwdService?wsdl";
        String soapaction = "http://service.hy.laneasy.com/";
        //        String url = "http://www.webxml.com.cn/WebServices/ValidateEmailWebService.asmx?wsdl";
        //        String soapaction = "http://WebXml.com.cn/";

        Call call = null;

        call = (Call) service.createCall();
        call.setTargetEndpointAddress(new java.net.URL(url));
        //        call.setTargetEndpointAddress(url);
        call.setOperationName(new QName(soapaction, "getNetworkNodePerf"));
        call.addParameter(new QName("", "jobId"), org.apache.axis.encoding.XMLType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
        call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//（标准的类型） 
        call.setUseSOAPAction(true);
        call.setSOAPActionURI(soapaction + "getNetworkNodePerf");
        String v = (String) call.invoke(new Object[] { "2627" });//调用方法并传递参数
        System.out.println(v);

        //        String a = Math.round(Double.parseDouble("800") / 1000D) + "Mbps";
        //        String a1 = Math.ceil(Long.parseLong("800") / 1000) + "Mbps";
        //        System.out.println(a + "--" + a1);

    }
}
